#ifndef _Button_h_
#define _Button_h_

#include "SDL.h"
#include "Gfx.h"

extern SDL_Surface *screen;

// Basic Button class
class Button {
  public:
    // Shallow copy is used (pointers)
    Button (SDL_Surface *pushed, SDL_Surface *released,
            Sint16 x, Sint16 y, void (*callback)(int), int param)

      : pushedState_(false), pushed_(pushed), released_(released), x_(x), y_(y), callback_(callback), param_(param), owner_(false), group_(-1)
    {
      w_ = pushed->w;
      h_ = pushed->h;
    }

    // Same remark: the difference is that we create the released
    // surface by blitting from a source image (in our case, the screen).
    Button (SDL_Surface *pushed, SDL_Surface *srcimg, Sint16 rx, Sint16 ry, Uint16 w, Uint16 h,
            Sint16 x, Sint16 y, void (*callback)(int), int param = 0)

           : pushedState_(false), pushed_(pushed), x_(x), y_(y), callback_(callback), param_(param), owner_(true), group_(-1)
    {
      w_ = w;
      h_ = h;
      SDL_Rect src = {rx,ry,w,h};
      SDL_Rect dst = {0,0,w,h};
      released_ = Gfx::instance()->createSurface(w,h,true);
      SDL_BlitSurface (srcimg, &src, released_,&dst);
    }

    ~Button () {
      if (owner_) {
        SDL_FreeSurface(released_);
        released_ = NULL;
      }
    }
    bool focused (Sint16 x, Sint16 y) {
      return (
        (x >= x_) && (x < x_+w_) && (y >= y_) && (y < y_+h_)
      );
    }
    void push     () {
      SDL_Rect src = { 0, 0, w_, h_ };
      SDL_Rect dst = { x_, y_, w_, h_ };
      SDL_BlitSurface (pushed_, &src, screen, &dst);
      SDL_UpdateRects (screen, 1, &dst);
      if (isRadio()) {
        if ((radioSelection_ != NULL) && (radioSelection_ != this)) {
          radioSelection_->release();
        }
        radioSelection_ = this;
        callback();
      }
      pushedState_ = true;
    }
    void release  () {
      SDL_Rect src = { 0, 0, w_, h_ };
      SDL_Rect dst = { x_, y_, w_, h_ };
      SDL_BlitSurface (released_, &src, screen, &dst);
      SDL_UpdateRects (screen, 1,&dst);
      pushedState_ = false;
    }
    void callback () {
      callback_(param_);
    }
    void setRadioGroup (int n) {
      group_ = n;
    }
    int getRadioGroup () {
      return group_;
    }
    bool isRadio () {
      return group_ != -1;
    }
    bool isPushed () {
      return pushedState_;
    }
  private:
    // Geometry
    Sint16 x_;
    Sint16 y_;
    Uint16 w_;
    Uint16 h_;
    // GFX
    SDL_Surface *pushed_;
    SDL_Surface *released_;
    // Behavior
    bool pushedState_;
    void (*callback_)(int);
    int param_;
    int group_;
    static Button *radioSelection_;
    // Mem management
    bool owner_;
};

#endif

